Matroid & Greedy Algorithm

매트로이드(Matroid)
M(S,l) 1. S는 유한 집합이다. 2. l은 S의 독립적(independent)부분집합들로 구성된 공집합이 아닌 집합이다. 독립적 부분 집합은 ∈l이고 A⊆B이면 A∈l이라고 말한다. l이 이런 특성을 만족시키면 상속성(hereditary)가 있다고 말한다. 여기서 공집합 ∅은 반드시 l의 원소임 3. A∈l,B∈l,|A|<|B|이면A∪{x}∈l인 x∈B−A가 존재한다. M이 교환 특성(exchange property)을 만족시킨다고 말한다.
그래픽 매트로이드(Graphic Matroid)
MG=(SG,lG) about 무방향 그래프G=(V, E) - SG는 G의 간선들의 집합인 E - A가 E의 부분집합일 때, A가 비순환(acyclic)이라는 것은 A∈lG의 필요충분조건이다. 부분 그래프 GA(V,A)가 포리스트를 이룬다는 것은 간선들의 집합 A가 독립적이라는 조건의 필요충분조건이다. G=(V, E)가 무방향 그래프이면, MG=(SG,lG) 매트로이드이다.
M=(S,l)에서 원소 x∉A가 A에 더해져도 독립성을 유지할 수 있다면 원소 x를 A∈l의 확장(extension)이라고 한다. A가 아무런 확장도 가지고 있지 않다면 최대(maximal)라고 말한다. 하나의 매트로이드 안에 있는 모든 최대 독립 부분 집합들은 크기가 같다. 그리픽 매트로이드에서 최대인 상태는 G의 모든 점을 |V|-1 개의 간선을 가진 자유 트리 == 신장 트리(spanning tree)
// Psudo code
Greedy(M, w):
A=emptySet;
M.S를 가중치 w값에 따라 단조감소하는 순서로 정렬
for(x \in M.S): // w(x)가 단조 감소하는 순서
if A \cup {x} \in M.l:
A=A \cup {x};
return A;
Unit-time task scheduling with Matroid
n개의 단위 시간 작업을 가지는 S={a_1, a_2, … , a_n};
n개의 정수 형태 최종 마감 시간(deadline) d_1, d_2, … , d_n의 집합;        1=\leq d_i \leq n
n개의 음수가 아닌 가중치(weight or penalty) w_1, w_2, w_3, …, w_n의 집합
#include <iostream>
#include <algorithm>
struct Act{
int s, d, w;
Act(){}
Act(int _s, int _d, int _w): s(_s), d(_d), w(_w) {}
~Act(){}
void set(int _s, int _d, int _w){
this->s=_s;
this->d=_d;
this->w=_w;
}
};
bool ActCmp(Act act1, Act act2){
return act1.w>act2.w;
}
struct Acts{
Act* arr;
int size, cap=0;
Acts(int _size): size(_size) {
this->arr=new Act[this->size];
}
void insert(int _s, int _d, int _w){
if(cap==size){
std::cout<<"Acts Full"<<std::endl;
exit(1);
}
arr[cap++].set(_s, _d, _w);
}
void sort(void){
std::sort(arr, arr+size, ActCmp);
}
int s(int ind){
return this->arr[ind].s;
}
int d(int ind){
return this->arr[ind].d;
}
int w(int ind){
return this->arr[ind].w;
}
};
struct Array{
int* arr;
int sz, cap=0;
Array(int _sz): sz(_sz) {
arr=new int[sz];
}
void insert(int ind){
this->arr[this->cap++]=ind;
}
void print(void){
for(int i=0; i<this->cap; ++i) std::cout<<arr[i]<<' ';
std::cout<<std::endl;
}
};
void GreedyActivitySelector(Acts acts, Array& index){
acts.sort();
int n=acts.size;
int ind=0;
int l=0;
for(int m=0; m<n; ++m){
int sum=0;
for(int k=0; k<=m; ++k){
if(acts.d(k)<=l) sum++;
}
if(sum<=m){
index.insert(m+1);
l++;
}
}
}
int main(void){
Acts acts(7);
Array index(7);
int s[7]={1, 2, 3, 4, 5, 6, 7};
int d[7]={4, 2, 4, 3, 1, 4, 6};
int w[7]={70, 60, 50, 40, 30, 20, 10};
for(int i=0; i<7; ++i) acts.insert(s[i], d[i], w[i]);
acts.sort();
GreedyActivitySelector(acts, index);
index.print();
return 0;
}
크기 순으로 정렬한 이후, Nt(A)≤t를 만족하는 경우에만 추가 모든 t에 대해서 Nt(A)≤t를 만족하는 집합 A는 독립적이다.(모두 가능)